<?php

declare (strict_types=1);
namespace App\Model;

use App\Cache\CacheKey;
use Carbon\Carbon;
use Hyperf\Database\Model\Collection;
use Hyperf\Database\Model\Events\Deleted;
use Hyperf\Database\Model\Events\Saving;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use HyperfExt\Jwt\Contracts\JwtSubjectInterface;

/**
 * @property int $id 
 * @property string $name 用户名
 * @property string $email 邮箱
 * @property string $password 密码
 * @property string $avatar 头像url
 * @property string $role 角色
 * @property string $status 状态
 * @property int $points 积分
 * @property ?Carbon $last_login_at 最后登录时间
 * @property string $last_login_ip 
 * @property ?Carbon $email_verified_at
 * @property Carbon $created_at
 * @property Carbon $updated_at
 *
 * @property-read Collection<Article> $articles
 * @property-read Collection<SystemLog> $systemLogs
 */
class User extends Model implements JwtSubjectInterface
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'users';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['id', 'name', 'email', 'password', 'avatar', 'role', 'status', 'points', 'last_login_at', 'last_login_ip', 'email_verified_at', 'created_at', 'updated_at'];
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'email_verified_at' => 'datetime', 'last_login_at' => 'datetime', 'points' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];

    public function articles()
    {
        return $this->hasMany(Article::class);
    }

    public function getJwtIdentifier()
    {
        return $this->getKey();
    }

    public function getJwtCustomClaims(): array
    {
        return [
            'role' => $this->role,
        ];
    }
    public function profile()
    {
        return $this->hasOne(UserProfile::class,'user_id','id');
    }

    /**
     * 当用户更新了role,password,status字段，需要重新登录，将签发时间为此时间点之前的token都标记为无效
     */
    public function saving(Saving $event)
    {
        $model = $event->getModel();
        if ($model->isDirty(['role', 'password', 'status'])) {
            $redis = ApplicationContext::getContainer()->get(Redis::class);
            $redis->setex(CacheKey::forbidTokenBefore($model->id), config('jwt.ttl'), time());
        }

        return true;
    }

    /**
     * 当删除用户的时候，需要关联
     */
    public function deleted(Deleted $event)
    {

    }
}